package com.cheng.example.excel.easyexcel.util.util;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.apache.commons.lang3.StringUtils;
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.map.JsonMappingException;
import org.codehaus.jackson.map.ObjectMapper;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * JSON转换工具类
 *
 * @date 2010-11-23
 * @since JDK 1.5
 * @author dingkui
 * @version 1.0
 *
 */
public class JsonUtil {

    /**
     *
     */
    public static ObjectMapper mapper;

    static {
        JsonUtil.mapper = new ObjectMapper();
    }

    /**
     * 将object转为json字符串
     *
     * @param pObj
     *      参数
     * @throws IOException
     *      异常
     * @throws JsonMappingException
     *      异常
     * @throws JsonGenerationException
     *      异常
     * @return String
     */
    public static String writeValue(Object pObj) throws JsonGenerationException, JsonMappingException, IOException {
        return JsonUtil.mapper.writeValueAsString(pObj);
    }

    /**
     * 将content转为java object
     *
     * @param <T>
     *      参数
     * @param pContent
     *      参数
     * @param pObj
     *      参数
     * @throws JsonParseException
     *      异常
     * @throws JsonMappingException
     *      异常
     * @throws IOException
     *      异常
     * @return Object
     */
    @SuppressWarnings("unchecked")
    public static <T> Object readValue(String pContent, Object pObj) throws JsonParseException, JsonMappingException,
            IOException {
        return JsonUtil.mapper.readValue(pContent, (Class<T>) pObj);
    }

    /**
     * 将json格式的字符串转换为javabean
     *
     * @param jsonStr
     * @param beanClazz
     * @return
     * @throws Exception
     */
    public static <T> T readBean(String jsonStr, Class<T> beanClazz)
            throws Exception {
        if (StringUtils.isBlank(jsonStr)) {
            return null;
        }
        JSONObject jsObj = JSONObject.parseObject(jsonStr);
        return jsObjToBean(jsObj, beanClazz);
    }

    @SuppressWarnings("unchecked")
    public static <T> T jsObjToBean(JSONObject jsObj, Class<T> beanClazz)
            throws Exception {
        T bean = beanClazz.newInstance();
        Method[] pubMethods = beanClazz.getMethods();
        outer: for (String jsPropKey : jsObj.keySet()) {
            Object jsPropValue = jsObj.get(jsPropKey);
            if (jsPropValue == null) {
                continue;
            }
            String jsPropName = jsPropKey;
            if (jsPropName.indexOf('_') >= 0) {
                jsPropName = StringUtils.replace(jsPropName, "_", "");
            }
            for (Method pubMethod : pubMethods) {
                if (pubMethod.getName().equalsIgnoreCase("set" + jsPropName)) {
                    Class<?> beanPropClazz = pubMethod.getParameterTypes()[0];
                    Object beanPropValue = null;
                    if (jsPropValue instanceof JSONObject) {
                        beanPropValue = jsObjToBean((JSONObject) jsPropValue,
                                beanPropClazz);
                    } else if (jsPropValue instanceof JSONArray) {
                        if (beanPropClazz != List.class
                                && beanPropClazz != ArrayList.class) {
                            throw new RuntimeException("目前只支持List属性");
                        }
                        ParameterizedType args = (ParameterizedType) (pubMethod
                                .getGenericParameterTypes()[0]);
                        Class<?> actuClazz = (Class<?>) args
                                .getActualTypeArguments()[0];
                        beanPropValue = new ArrayList<Object>();
                        JSONArray jskjArray = (JSONArray) jsPropValue;
                        if (!jskjArray.isEmpty()) {
                            for (int i = 0; i < jskjArray.size(); i++) {
                                if (jskjArray.get(i).getClass() == JSONObject.class) {
                                    ((List<Object>) beanPropValue)
                                            .add(jsObjToBean(
                                                    (JSONObject) (jskjArray
                                                            .get(i)), actuClazz));
                                }
                            }
                        }
                    } else if (beanPropClazz == String.class) {
                        beanPropValue = jsObj.getString(jsPropKey);
                    } else if (StringUtils.isBlank(jsObj.getString(jsPropKey))) {
                        continue outer;
                    } else if (Number.class.isAssignableFrom(beanPropClazz)) {
                        beanPropValue = beanPropClazz.getConstructor(
                                String.class).newInstance(
                                jsObj.getString(jsPropKey));
                    } else if (beanPropClazz == Date.class) {
                        beanPropValue = DateUtil.getDate(jsObj
                                .getString(jsPropKey));
                    } else if (beanPropClazz == int.class) {
                        beanPropValue = Integer.parseInt(jsObj
                                .getString(jsPropKey));
                    } else if (beanPropClazz == byte.class) {
                        beanPropValue = Byte.parseByte(jsObj
                                .getString(jsPropKey));
                    } else if (beanPropClazz == float.class) {
                        beanPropValue = Float.parseFloat(jsObj
                                .getString(jsPropKey));
                    } else if (beanPropClazz == double.class) {
                        beanPropValue = Double.parseDouble(jsObj
                                .getString(jsPropKey));
                    } else if (beanPropClazz == short.class) {
                        beanPropValue = Short.parseShort(jsObj
                                .getString(jsPropKey));
                    } else {
                        throw new RuntimeException("不支持的数据类型:"
                                + jsPropValue.getClass().getName() + " "
                                + beanPropClazz);
                    }
                    pubMethod.invoke(bean, beanPropValue);
                }
            }
        }
        return bean;
    }

    /**
     * 将json格式的字符串转换为javabean的List
     *
     * @param jsonStr
     * @param beanClazz
     * @return
     * @throws Exception
     */
    public static <T> List<T> readBeanList(String jsonStr, Class<T> beanClazz)
            throws Exception {
        if (StringUtils.isBlank(jsonStr)) {
            return null;
        }
        List<T> beanList = new ArrayList<T>();
        JSONArray jsArray = JSONObject.parseArray(jsonStr);
        if (!jsArray.isEmpty()) {
            for (int i = 0; i < jsArray.size(); i++) {
                beanList.add(jsObjToBean((JSONObject) (jsArray.get(i)),
                        beanClazz));
            }
        }
        return beanList;
    }
}
